AWS ELBの社内向け構成ガイドを公開してみる 負荷分散編 – Cross-Zone Routingを踏まえて
ども、大瀧です。
最近、お客さまからの問い合わせからElastic Load Balancing(ELB)の負荷分散について調べ社内資料としてまとめる機会がありました。せっかくなので、ブログ記事として公開してみます。内容は随時アップデートしますので、ツッコミ・ご指摘があればぜひお願いします!
負荷分散の仕組み
ELBは、クライアントのリクエストを受け付けEC2インスタンスにトラフィックを転送するために、2種類の負荷分散を組み合わせて動作します。 スケーラビリティと冗長性のために、ELBはロードバランサの機能を提供するノードを複数動作させるはたらきがあり、クライアントから複数のノードへアクセスを分散させるためにDNSラウンドロビン、ノードからEC2インスタンスへのトラフィック転送を分散させるためにLeast Connsという手法を用いています。
DNSラウンドロビン
DNSラウンドロビンはその名の通り、DNSの仕組みを利用する方法です。クライアントがELBのDNS名の名前解決を行う際に、DNSサーバーがレスポンスとして返すレコードを動的に切り替えることで、アクセスするELBノードを分散させます。ELBのDNS名について問合せを行うhostコマンドの実行例を以下に示します。
$ host normal-elb-test-1234567890.ap-northeast-1.elb.amazonaws.com normal-elb-test-1234567890.ap-northeast-1.elb.amazonaws.com has address AAA.AAA.AAA.AAA normal-elb-test-1234567890.ap-northeast-1.elb.amazonaws.com has address BBB.BBB.BBB.BBB $ host normal-elb-test-1234567890.ap-northeast-1.elb.amazonaws.com normal-elb-test-1234567890.ap-northeast-1.elb.amazonaws.com has address BBB.BBB.BBB.BBB normal-elb-test-1234567890.ap-northeast-1.elb.amazonaws.com has address AAA.AAA.AAA.AAA $
ELBは、作成時に指定するAvailability Zoneごと *1に少なくとも1ノード作成されるため、上記例では2ゾーンを指定したことで、2つのレコードが返ってきています。ちなみにELBノードは、ELBにアクセスが集中する場合には自動でノード数を増やす(スケールアウトする)ようになっており、4レコード以上返ってくる場合もあります。
気をつけなければならない性質として、クライアントがDNSの応答をキャッシュすることがあります。 上記のように、DNSサーバーは都度レコードの順番を変えて返答しますが、一般のクライアントはそのうち先頭のレコードを選択し、そのレコードをキャッシュします。キャッシュを保持している間は同一のELBノードへのアクセスを続けるため、内部向けELBや特定の顧客向けAPI用途など、クライアント数が少ない場合は思うようにアクセスが分散しない場合があります。後述のLeast Connsでうまく分散するように意識しましょう。
Least Conns
ELBノードがクライアントから受け取ったトラフィックをどのEC2インスタンスに転送するかを決める際には、Least Conns(最少接続数)を評価します。アルゴリズムの詳細は公開されていませんが、一般的な解釈としてはトラフィック数を考慮して、低負荷なEC2インスタンスにトラフィックを転送する仕組みと考えてよいでしょう。
こちらの注意点としては、初期構成ではELBノードが転送対象とするEC2インスタンスの範囲が同一Availability Zoneに限られることがあります。最近、この振るまいを変更する機能が追加されその機能をCross-Zone Routingと呼ぶことから、初期構成の同一Availability Zoneに限定する振る舞いをここでは便宜上Same-Zone Routingと呼んでみます。
Same-Zone Routing
Same-Zone Routingでは、ELBノードはEC2インスタンスのうち同一Availability Zoneにあるインスタンスにのみトラフィックを転送します。そのため、DNSラウンドロビンで均等に分散できていても、Availability Zoneごとに配置するEC2インスタンス数がまちまちだと、不均等な分散になってしまう恐れがあります。Availability ZoneごとのEC2インスタンス数はなるべく同数にしましょう。
Cross-Zone Routing
Cross-Zone Routingでは、ELBノードはAvailability Zoneに関係なく配下にある全てのEC2インスタンスにトラフィックを転送します。このため、DNSラウンドロビンによってELBノードへのアクセスが偏ってしまう場合でも、Cross-Zone Routingによって偏りを吸収する効果が期待できます。極端な例として、ELB作成時のAvailability Zoneを1つのみ指定しても問題なく動作しますが、可用性の観点から複数のAvailability Zoneを選んだ方が無難でしょう。
ただし、複数のELBノードからのトラフィックが各EC2インスタンスに転送されるため、ELBノードのLeast Connsによる分散が正確に評価されない可能性があります。Least Connsの詳細な仕様が公開されていないため推測になりますが、評価がELBノードごとに別々に行われているとすると、あるELBノードでは高負荷と評価されたEC2インスタンスが、他のELBノードでは低負荷と評価される可能性が考えられます。
また、Availability ZoneをまたぐEC2間のデータ転送には課金が発生しますが、ドキュメントにはELBノードからEC2インスタンスに転送する際のデータ転送は課金されないとあり、(未検証ですが)Cross-Zone Routingを設定する場合の追加コストを意識する必要はなさそうです。
ベストプラクティス
さて、ここまで教科書的にELBの分散の仕組みを説明してきましたが、実際のケースにはどのように落とし込んでいけばよいでしょうか。私的見解として、以下2つがオススメです。
Availability Zoneに1台ずつの小規模な構成では、Cross-Zone Routing!
Design of Failureの原則に則って、Availability Zoneをまたいだとりあえずの2台構成で...なんていう場合は、Cross-Zone Routingを設定しましょう。小規模構成ではクライアント数も少ないという場合が多く、DNSラウンドロビンによる偏りの影響が出やすいです。それを、Cross-Zone Routingで吸収できるメリットは大きいと思います。
中〜大規模構成では、台数だけ気をつけて初期構成(Same-Zone Routing)のまま。
Availability Zoneあたり2台以上動作する構成では、Same-Zone Routingでも十分に分散することが期待できるため、Availability Zoneごとの台数をなるべく同一になるようにすれば初期構成のままで問題ないでしょう。台数が多いとLeast Connsの評価への依存が大きくなるため、Cross-Zone Routingのリスクを押さえる目的もあります。
正常稼働時であれば同一数を維持するのは難しくないと思いますが、メンテナンスやアプリケーションのアップデート/デプロイのためにインスタンスを入れ替えるときは、入れ替え順序や配置するゾーンに気をつけて計画および作業を行うようにしましょう。
ちなみに、EC2インスタンスを自動で管理するAuto Scalingは、特別な設定をしなくてもインスタンス数がAvailability Zoneごとに同一になるようにインスタンスを増減してくれるので、とても捗ります!(ステマ)
まとめ
もう一度ベストプラクティスを繰り返しておきます。
- Availability Zoneごとに配置するインスタンス数は、なるべく同一にする。
- Availability Zoneに1台ずつの小規模な構成では、Cross-Zone Routingを設定する。
- 中大規模な構成では、台数だけ気をつけて初期構成(Same-Zone Routing)のまま。
この辺りの動きは、ELBを含めたAWSのアーキテクトにはもちろんELB周りのトラブルシューティングにも役立つことがありますので、理解を深めておきたいところですね!
参考資料
脚注
- 厳密には、Availability Zoneごと指定するVPCサブネット ↩